-- ======================================================================
--  Hell Watch Lua IO App
-- 
-- Copyright 2014 Hell-Prototypes
--
-- http://www.hellprototypes.com
--
-- This is free software, licensed under the terms of the GNU General
-- Public License as published by the Free Software Foundation.
-- ======================================================================
module(..., package.seeall);

-- : 10 0100 00 214601360121470136007EFE09D21901 40
function Read_File(file_name)
	-- print("file_name: " .. file_name)

	local str_data = ""

	local byte_count = 0
	local address = 0
	local record_type = 0
	local checksum = 0
	
	local raw_data = {}
	local byte_data = 0
	local min_address = 0xffff
	local max_address = 0
	local check = 0
    local space_skip = false

	local file = io.open(file_name, "r")
	if file == nil then
		return min_address, raw_data
	end

	for line in file:lines() do
		--print(line)
		byte_count = tonumber(line:sub(2,3), 16)
		address = tonumber(line:sub(4,7), 16)
		record_type = tonumber(line:sub(8,9), 16)
		checksum = tonumber(line:sub(line:len()-1, line:len()), 16)
		
		check = byte_count + bit32.rshift(address, 8) + bit32.band(address, 0xff) + record_type + checksum
		
		--print("byte_count " .. byte_count)
		--print("address " .. address)
		--print("record_type " .. record_type)
		--print("checksum " .. checksum)
		
		if record_type == 0x00 then
            if space_skip == false then
    			str_data = line:sub(10, line:len()-2)
    			if byte_count * 2 ~= str_data:len() then
    				print("byte_count * 2 ~= str_data:len()")
    				break
    			end

    			if address < min_address  then
    				min_address = address
    			end
    			if address + byte_count > max_address then
    				max_address = address + byte_count
    			end

    			for i=1, byte_count do
    				local data = tonumber(str_data:sub(2 * i - 1, 2 * i), 16)
    				check = check + data
    				raw_data[address + i] = data
    			end

    			if bit32.band(check, 0xff) ~= 0 then
    				raw_data = nill
    				print("Checksum error in line:\r\n" .. line)
    				break
    			end
            end
        elseif record_type == 0x04 then
            str_data = line:sub(10, line:len()-2)
			if byte_count * 2 ~= str_data:len() then
				print("* byte_count * 2 ~= str_data:len()")
				break
			end
            local addr = tonumber(str_data:sub(1, 4), 16)
            if addr == 0 then
                space_skip = false
            else
                space_skip = true
            end
		elseif record_type == 0x01 then
            -- End Of File record Work DONE
			break
        else
            print("<iHEX> Eror: unsupport record types: " .. record_type)
            raw_data = nil
            file:close()
	        return 0, raw_data
		end
	end
	for i=1, max_address do
		if raw_data[i] == nil then
			raw_data[i] = 0xFF
		end
	end
	
	file:close()
	
	return min_address, raw_data
end

--[[
-- Debug code
g_raw_data = {}
g_start_addr = 0

g_start_addr, g_raw_data = Read_File("BreathingLED.hex")

if type(g_raw_data) == "table" then
	for i=1, #g_raw_data do
		io.write(string.format("%02xH,", g_raw_data[i]):upper())
		if i%16 == 0 then
			print("")
		end
	end
	
	print(string.format("\r\nstart address is : 0x%04x", g_start_addr))
end
--]]